package org.web.accesscontrollist.server.biz.impl;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.web.accesscontrollist.sdk.biz.AclUserResourceBindingBiz;
import org.web.accesscontrollist.sdk.dto.*;
import org.web.accesscontrollist.sdk.dto.constant.AclResourceConstant;
import org.web.accesscontrollist.sdk.dto.query.QueryAclUserResourceBindingRequest;
import org.web.accesscontrollist.server.domain.AclResourceDetailDO;
import org.web.accesscontrollist.server.domain.AclUserResourceBindingDO;
import org.web.accesscontrollist.server.domain.query.QueryAclResourceDetail;
import org.web.accesscontrollist.server.domain.query.QueryAclUserResourceBinding;
import org.web.accesscontrollist.server.service.AclResourceDetailService;
import org.web.accesscontrollist.server.service.AclUserResourceBindingService;
import org.web.accesscontrollist.server.service.OperatorService;
import org.web.base.domain.ResultDO;
import org.web.base.domain.exception.ResultMessageEnum;
import org.web.base.domain.helper.ResultHelper;
import org.web.base.domain.helper.ServiceExceptionHelper;
import org.web.base.domain.helper.ValidationHelper;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Service("aclUserResourceBindingBiz")
public class AclUserResourceBindingBizImpl implements AclUserResourceBindingBiz, AclResourceConstant {

    private static final Logger logger = Logger.getLogger(AclUserResourceBindingBizImpl.class);

    @Resource
    private AclResourceDetailService aclResourceDetailService;

    @Resource
    private AclUserResourceBindingService aclUserResourceBindingService;

    @Resource
    private OperatorService operatorService;

    @Override
    public ResultDO<List<AclUserResourceBindingDTO>> saveUserResourceBindingBatch(SaveUserResourceBindingBatchDTO saveUserResourceBindingBatchDTO) {
        ResultDO<List<AclUserResourceBindingDTO>> resultDO = new ResultDO<>();
        List<String> errorList = new ArrayList<>();
        try {

            // 参数校验
            AclResourceHelper.checkSaveUserResourceBindingBatchDTO(saveUserResourceBindingBatchDTO);
            resultDO.setDomain(saveUserResourceBindingBatchDTO.getAclUserResourceBindingDTOList());
            // 权限校验
            OperatorDTO operatorDTO = saveUserResourceBindingBatchDTO.getOperatorDTO();
            operatorService.judgeOperatorByAccessKey(operatorDTO.getBusinessLine(), operatorDTO.getAccessKey());

            // 判断绑定的detail信息是否存在。
            Map<String, AclUserResourceBindingDTO> aclUserResourceBindingDOMap = new HashMap<>();
            List<AclUserResourceBindingDO> aclUserResourceBindingDOList = new ArrayList<>();
            resultDO.setDomain(saveUserResourceBindingBatchDTO.getAclUserResourceBindingDTOList());
            Date current = new Date();
            for (AclUserResourceBindingDTO aclUserResourceBindingDTO : saveUserResourceBindingBatchDTO.getAclUserResourceBindingDTOList()) {
                AclUserResourceBindingDO aclUserResourceBindingDO = new AclUserResourceBindingDO();
                QueryAclResourceDetail queryAclResourceDetail = new QueryAclResourceDetail();
                queryAclResourceDetail.setBusinessLine(aclUserResourceBindingDTO.getBusinessLine());
                queryAclResourceDetail.setDefinitionName(aclUserResourceBindingDTO.getDefinitionName());
                queryAclResourceDetail.setDetailName(aclUserResourceBindingDTO.getDetailName());
                AclResourceDetailDO aclResourceDetailDOFromDB = aclResourceDetailService.selectOneAclResourceDetail(queryAclResourceDetail);
                if (ObjectUtils.isEmpty(aclResourceDetailDOFromDB)) {
                    errorList.add(aclUserResourceBindingDTO.getUniqueDetailResourceKey() + ",没有关联的资源详情信息，请先维护资源信息。 ");
                } else {
                    aclUserResourceBindingDTO.setAclResourceDetailId(aclResourceDetailDOFromDB.getAclResourceDetailId());
                    aclUserResourceBindingDTO.setAclResourceDefinitionId(aclResourceDetailDOFromDB.getAclResourceDefinitionId());
                    aclUserResourceBindingDTO.setFirstLevel(aclResourceDetailDOFromDB.getFirstLevel());
                    aclUserResourceBindingDTO.setSecondLevel(aclResourceDetailDOFromDB.getSecondLevel());
                    aclUserResourceBindingDTO.setThirdLevel(aclResourceDetailDOFromDB.getThirdLevel());
                    aclUserResourceBindingDTO.setFourthLevel(aclResourceDetailDOFromDB.getFourthLevel());
                    aclUserResourceBindingDTO.setFifthLevel(aclResourceDetailDOFromDB.getFifthLevel());
                    aclUserResourceBindingDTO.setResourceLevel(aclResourceDetailDOFromDB.getResourceLevel());
                    BeanUtils.copyProperties(aclUserResourceBindingDO, aclUserResourceBindingDTO);
                    aclUserResourceBindingDO.setUpdateTime(current);
                }
                aclUserResourceBindingDOList.add(aclUserResourceBindingDO);
                aclUserResourceBindingDOMap.put(aclUserResourceBindingDTO.getUniqueDetailResourceKey(), aclUserResourceBindingDTO);
            }
            if (errorList.size() > 0) {
                throw ServiceExceptionHelper.buildServiceException(ResultMessageEnum.DATA_NOT_EXIST, errorList);
            }

            // 保存用户、资源、角色绑定关系。有优化空间，节省访问DB次数。
            for (AclUserResourceBindingDO aclUserResourceBindingDO : aclUserResourceBindingDOList) {
                QueryAclUserResourceBinding queryAclUserResourceBinding = new QueryAclUserResourceBinding();
                queryAclUserResourceBinding.setAclResourceDetailId(aclUserResourceBindingDO.getAclResourceDetailId());
                queryAclUserResourceBinding.setRoleName(aclUserResourceBindingDO.getRoleName());
                queryAclUserResourceBinding.setUserNum(aclUserResourceBindingDO.getUserNum());
                AclUserResourceBindingDO aclUserResourceBindingDOFromDB = aclUserResourceBindingService.selectOneAclUserResourceBinding(queryAclUserResourceBinding);
                AclUserResourceBindingDTO aclUserResourceBindingDTO = aclUserResourceBindingDOMap.get(aclUserResourceBindingDO.getUniqueDetailResourceKey());
                if (ObjectUtils.isNotEmpty(aclUserResourceBindingDOFromDB)) {
                    aclUserResourceBindingDO.setAclUserResourceBindingId(aclUserResourceBindingDOFromDB.getAclUserResourceBindingId());
                    aclUserResourceBindingService.updateAclUserResourceBindingByAclUserResourceBindingId(aclUserResourceBindingDO);
                    aclUserResourceBindingDTO.setCreateTime(aclUserResourceBindingDOFromDB.getCreateTime());
                    aclUserResourceBindingDTO.setUpdateTime(aclUserResourceBindingDO.getUpdateTime());
                } else {
                    aclUserResourceBindingDO.setCreateTime(current);
                    aclUserResourceBindingService.insertAclUserResourceBinding(aclUserResourceBindingDO);
                    aclUserResourceBindingDTO.setCreateTime(aclUserResourceBindingDO.getCreateTime());
                    aclUserResourceBindingDTO.setUpdateTime(aclUserResourceBindingDO.getUpdateTime());
                }
                aclUserResourceBindingDTO.setExecuteSuccess(true);
            }

        } catch (Exception e) {
            logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            resultDO = ResultHelper.buildResultDOByException(e);
        }
        return resultDO;
    }

    @Override
    public ResultDO<List<AclUserResourceBindingDTO>> selectAclUserResourceBindingList(QueryAclUserResourceBindingRequest queryAclUserResourceBindingRequest) {
        ResultDO<List<AclUserResourceBindingDTO>> resultDO;
        try {
            ValidationHelper.validateAndThrow(QueryAclUserResourceBindingRequest.class, queryAclUserResourceBindingRequest);
            QueryAclUserResourceBinding queryAclUserResourceBinding = new QueryAclUserResourceBinding();
            BeanUtils.copyProperties(queryAclUserResourceBinding, queryAclUserResourceBindingRequest);
            ResultDO<List<AclUserResourceBindingDO>> selectAclUserResourceBindingListResult = aclUserResourceBindingService.selectAclUserResourceBindingListResult(queryAclUserResourceBinding);
            resultDO = ResultHelper.buildResultDOByResultDO(selectAclUserResourceBindingListResult, AclUserResourceBindingDTO.class);
        } catch (Exception e) {
            logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            resultDO = ResultHelper.buildResultDOByException(e);
        }
        return resultDO;
    }
}
